import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import WipMachineMaintain from '@main/entities/service/admin/wip/wip-machine-maintain.entity';
import WipMachineMaintainList from '@main/entities/service/admin/wip/wip-machine-maintain-list.entity';
import SysDictionary from '@main/entities/service/admin/sys/sys-dictionary.entity';
import { In, Repository, Like, Between } from 'typeorm';
import { UtilService } from '@main/shared/services/util.service';
import { ApiException } from '@main/common/exceptions/api.exception';
import { generateExcelFn } from '@main/excel';
import { SysOperationLogService } from '../../system/operationLog/operationLog.service';
import { format } from 'date-fns';

@Injectable()
export class WipMachineMaintainService {
  constructor(
    @InjectRepository(WipMachineMaintain)
    private machineMaintainRepository: Repository<WipMachineMaintain>,
    @InjectRepository(WipMachineMaintainList)
    private machineMaintainListRepository: Repository<WipMachineMaintainList>,
    private util: UtilService,
    @InjectRepository(SysDictionary)
    private dictionaryRepository: Repository<SysDictionary>,
    private operationLogService: SysOperationLogService
  ) {}

  /**
   * 列举所有角色：除去超级管理员
   */
  async list() {
    const machineMaintainList = await this.machineMaintainRepository.find();

    await Promise.all(
      machineMaintainList.map(async (machineMaintain) => {
        const { machineMaintainCode } = machineMaintain;
        const machineMaintainList = await this.machineMaintainListRepository.find({
          where: { machineMaintainCode },
        });

        machineMaintain['machineMaintainList'] = machineMaintainList;
      })
    );

    return machineMaintainList;
  }

  /**
   * 分页加载设备保养管理
   */
  async page(data, lang) {
    const { pageSize, pageNum, entity = {} } = data;

    const {
      machineMaintainCode,
      machineMaintainName,
      machineCode,
      maintenanceUser,
      maintenanceStatus,
      isMaintenance,
      planMaintenanceDate,
      periodRateCodeList,
      ids = [],
    } = entity;

    const where = {
      machineCode: Like(`%${machineCode}%`),
      machineMaintainCode: Like(`%${machineMaintainCode}%`),
      machineMaintainName: Like(`%${machineMaintainName}%`),
      maintenanceUser: Like(`%${maintenanceUser}%`),
      maintenanceStatus: Like(`%${maintenanceStatus}%`),
      isMaintenance: Like(`%${isMaintenance}%`),
    };

    if (planMaintenanceDate && planMaintenanceDate.length === 2) {
      where['planMaintenanceDate'] = Between(planMaintenanceDate[0], planMaintenanceDate[1]);
    }

    if (periodRateCodeList && periodRateCodeList.length) {
      where['periodRateCode'] = In(periodRateCodeList);
    }

    if (ids && ids.length) {
      where['id'] = In(ids);
    }

    const [list, total] = await this.machineMaintainRepository.findAndCount({
      where,
      order: {
        updateTime: 'DESC',
      },
      take: pageSize,
      skip: (pageNum - 1) * pageSize,
    });

    const newList: any = await Promise.all(
      list?.map(async (item) => {
        const { maintenanceStatus, isMaintenance, maintenanceDate, planMaintenanceDate } = item;
        if (maintenanceDate) {
          item.maintenanceDate = format(new Date(maintenanceDate), 'yyyy-MM-dd') as any;
        }
        if (planMaintenanceDate) {
          item.planMaintenanceDate = format(new Date(planMaintenanceDate), 'yyyy-MM-dd') as any;
        }
        let isMaintain = await this.dictionaryRepository.find({
          where: { dictionaryTypeCode: 'is_maintain', languageType: lang },
        });
        item.isMaintenance =
          isMaintain
            ?.map((item) => {
              return {
                label: item.dictionaryName,
                value: item.dictionaryCode,
              };
            })
            ?.find((item) => item.value === isMaintenance)?.label || '-';

        let maintainStatus = await this.dictionaryRepository.find({
          where: { dictionaryTypeCode: 'maintenance_status', languageType: lang },
        });
        item.maintenanceStatus =
          maintainStatus
            ?.map((item) => {
              return {
                label: item.dictionaryName,
                value: item.dictionaryCode,
              };
            })
            ?.find((item) => item.value === maintenanceStatus)?.label || '-';
        return {
          ...item,
        };
      })
    );

    return [newList, total];
  }

  async export(dto, lang) {
    const [list] = await this.page(dto, lang);

    if (!list || !(list as any).length) {
      throw new ApiException(10052);
    }

    const dataList = list.map((item) => {
      return {
        ...item,
      };
    });

    return await generateExcelFn(
      {
        sheetName: 'machineMaintain',
        mainHeaderList: [
          {
            label: 'machineMaintainCode',
          },
          {
            label: 'machineMaintainName',
          },
          {
            label: 'machineCode',
          },
          {
            label: 'machineName',
          },
          {
            label: 'periodRateName',
          },
          {
            label: 'machineModel',
          },
          {
            label: 'planMaintenanceDate',
          },
          {
            label: 'maintenanceUser',
          },
          {
            label: 'maintenanceStatus',
          },
          {
            label: 'maintenanceDate',
          },
          {
            label: 'isMaintenance',
          },
        ],
        dataList,
      },
      lang
    );
  }

  /**
   * 增加设备保养管理
   */
  async add(data, user, mac, ip, syncHostSqlite, isAutoAdd = '0') {
    const databaseOperationLogList = [];

    const databaseOperationLogList1 = [];

    const {
      machineMaintainName,
      machineCode,
      machineName,
      machineModel,
      periodRateCode,
      periodRateName,
      planMaintenanceDate,
      maintenanceUser,
      maintenanceStatus,
      remark,
      machineMaintainList,
      // createTime,
    } = data;

    const machineMaintainCode = `BY${this.util.nowDateValue()}${this.util.generateRandomNumberValue(
      4
    )}`;

    const result = await this.machineMaintainRepository.find({
      where: { machineMaintainCode },
    });

    if (result && result.length) {
      this.add(data, user, mac, ip, syncHostSqlite);

      return;
    }

    const machineMaintain = await this.machineMaintainRepository.insert({
      machineMaintainCode,
      machineMaintainName,
      machineCode,
      machineName,
      machineModel,
      periodRateCode,
      periodRateName,
      planMaintenanceDate,
      maintenanceUser,
      maintenanceStatus,
      maintenanceDate: isAutoAdd === '0' ? null : new Date().getTime(),
      isMaintenance: isAutoAdd === '0' ? '1' : '0',
      isAutoAdd,
      remark,
      createName: isAutoAdd === '0' ? user.nickName : null,
      createUserName: isAutoAdd === '0' ? user.userName : null,
      updateName: isAutoAdd === '0' ? user.nickName : null,
      updateUserName: isAutoAdd === '0' ? user.userName : null,
      // createTime,
    });

    databaseOperationLogList.push({
      type: 'add',
      dataType: 'obj',
      database: 'WipMachineMaintain',
      checkOnlyKeyList: [],
      data: machineMaintain,
      whereObj: null,
      remark: `WipMachineMaintain表新增数据`,
    });

    await this.operationLogService.add(
      {
        type: 'add',
        msg: `设备保养记录管理模块新增设备保养记录`,
        databaseOperationLogList,
        remark: `新增设备保养记录${data.machineMaintainName}`,
        mac,
        ip,
        syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
      },
      user
    );

    const machineMaintainList1 = await this.machineMaintainListRepository.insert(
      machineMaintainList.map((item) => ({ ...item, machineMaintainCode }))
    );

    databaseOperationLogList1.push({
      type: 'add',
      dataType: 'obj',
      database: 'WipMachineMaintainList',
      checkOnlyKeyList: [],
      data: machineMaintainList1,
      whereObj: null,
      remark: `WipMachineMaintainList表新增数据`,
    });

    await this.operationLogService.add(
      {
        type: 'add',
        msg: `设备保养记录管理模块项目列表新增设备保养记录`,
        databaseOperationLogList1,
        remark: `项目列表新增数据`,
        mac,
        ip,
        syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
      },
      user
    );
  }

  /**
   * 更新设备保养管理
   */
  async update(data, user, mac, ip, syncHostSqlite) {
    const databaseOperationLogList = [];
    const databaseOperationLogList1 = [];
    const {
      id,
      machineMaintainName,
      planMaintenanceDate,
      maintenanceStatus,
      isMaintenance,
      remark,
      machineMaintainList,
      machineMaintainCode,
    } = data;

    await this.machineMaintainRepository.update(
      { id },
      {
        machineMaintainName,
        planMaintenanceDate,
        maintenanceStatus,
        isMaintenance,
        remark,
        updateName: user.nickName,
        updateUserName: user.userName,
      }
    );
    databaseOperationLogList.push({
      type: 'update',
      dataType: 'obj',
      database: 'WipMachineMaintain',
      checkOnlyKeyList: [],
      data: {
        machineMaintainName,
        planMaintenanceDate,
        maintenanceStatus,
        isMaintenance,
        remark,
        updateName: user.nickName,
        updateUserName: user.userName,
      },
      whereObj: { id },
      remark: `WipMachineMaintain表更新设备保养记录信息`,
    });
    await this.operationLogService.add(
      {
        type: 'update',
        msg: `设备保养记录管理模块更新设备保养记录`,
        databaseOperationLogList,
        remark: `更新设备保养记录${data.machineMaintainName}`,
        mac,
        ip,
        syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
      },
      user
    );

    if (machineMaintainList && machineMaintainList.length) {
      await this.machineMaintainListRepository.delete({
        machineMaintainCode,
      });
      databaseOperationLogList1.push({
        type: 'delete',
        dataType: 'array',
        database: 'WipMachineMaintainList',
        checkOnlyKeyList: [],
        data: null,
        whereObj: null,
        remark: `WipMachineMaintainList表删除设备保养记录信息`,
      });
      await this.operationLogService.add(
        {
          type: 'delete',
          msg: `设备保养记录管理模块项目列表删除设备保养记录(更新时)`,
          databaseOperationLogList1,
          remark: `(更新时)删除设备保养记录信息`,
          mac,
          ip,
          syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
        },
        user
      );
      const machineMaintainList1 = await this.machineMaintainListRepository.insert(
        machineMaintainList.map((item) => ({ ...item, machineMaintainCode }))
      );
      databaseOperationLogList1.push({
        type: 'add',
        dataType: 'obj',
        database: 'WipMachineMaintainList',
        checkOnlyKeyList: [],
        data: machineMaintainList1,
        whereObj: null,
        remark: `WipMachineMaintainList表新增数据`,
      });

      await this.operationLogService.add(
        {
          type: 'add',
          msg: `设备保养记录管理模块项目列表新增设备保养记录(更新时)`,
          databaseOperationLogList1,
          remark: `(更新时)项目列表新增数据`,
          mac,
          ip,
          syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
        },
        user
      );
    }
  }

  /**
   * 根据Id数组删除设备保养管理
   */
  async delete(idList, user, mac, ip, syncHostSqlite) {
    const databaseOperationLogList = [];
    const databaseOperationLogList1 = [];
    const machineMaintainList = await this.machineMaintainRepository.find({
      where: {
        id: In(idList),
      },
    });

    for (let i = 0; i < machineMaintainList.length; i++) {
      const { machineMaintainCode } = machineMaintainList[i];
      await this.machineMaintainListRepository.delete({ machineMaintainCode });
      databaseOperationLogList1.push({
        type: 'delete',
        dataType: 'array',
        database: 'WipMachineMaintainList',
        checkOnlyKeyList: [],
        data: null,
        whereObj: idList,
        remark: `WipMachineMaintainList表删除数据`,
      });
      await this.operationLogService.add(
        {
          type: 'delete',
          msg: `设备保养记录管理模块项目列表删除设备保养记录(删除时)`,
          databaseOperationLogList1,
          remark: `(删除时)项目列表删除数据`,
          mac,
          ip,
          syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
        },
        user
      );
    }

    await this.machineMaintainRepository.delete({ id: In(idList) });

    databaseOperationLogList.push({
      type: 'delete',
      dataType: 'array',
      database: 'WipMachineMaintain',
      checkOnlyKeyList: [],
      data: null,
      whereObj: idList,
      remark: `WipMachineMaintain表删除设备保养记录信息`,
    });
    await this.operationLogService.add(
      {
        type: 'delete',
        msg: `设备保养记录管理模块删除设备保养记录信息`,
        databaseOperationLogList,
        remark: `删除设备保养记录信息`,
        mac,
        ip,
        syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
      },
      user
    );
  }

  /**
   * 根据id获取设备保养管理
   */
  async info(id) {
    const machineMaintain = await this.machineMaintainRepository.findOne({
      where: { id },
    });

    if (machineMaintain) {
      const { machineMaintainCode } = machineMaintain;

      const machineMaintainList = await this.machineMaintainListRepository.find({
        where: { machineMaintainCode },
      });

      machineMaintain['machineMaintainList'] = machineMaintainList;

      return machineMaintain;
    }
  }
}
